<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vConsole: Network</title>
  <link href="./lib/weui.min.css" rel="stylesheet"/>
  <link href="./lib/demo.css" rel="stylesheet"/>

  <script src="https://unpkg.com/axios/dist/axios.min.js" async></script>
  <script src="https://unpkg.com/zepto/dist/zepto.js" async></script>
  <script src="https://unpkg.com/wavesurfer.js" async></script>
  <script src="../dist/vconsole.min.js"></script>
</head>
<body ontouchstart>
  <div class="page">
    <div class="section">
      <div class="hd">XMLHttpRequest</div>

      <a onclick="getAjax()" href="javascript:;" class="weui_btn weui_btn_default">GET XHR</a>
      <a onclick="putAjax()" href="javascript:;" class="weui_btn weui_btn_default">PUT XHR</a>
      <a onclick="postAjax()" href="javascript:;" class="weui_btn weui_btn_default">POST XHR (Data: Object)</a>
      <a onclick="postAjax('json')" href="javascript:;" class="weui_btn weui_btn_default">POST XHR (Data: JSON String)</a>
      <a onclick="postAjax('', 'massive.json')" href="javascript:;" class="weui_btn weui_btn_default">POST XHR (Massive Resp)</a>
      <a onclick="optionsXHR()" href="javascript:;" class="weui_btn weui_btn_default">OPTIONS XHR</a>
      <a onclick="xhrStream('flv')" href="javascript:;" class="weui_btn weui_btn_default">XHR Chunked: flv</a>
      <a onclick="xhrStream('json')" href="javascript:;" class="weui_btn weui_btn_default">XHR Chunked: json</a>
    </div>

    <div class="section">
      <div class="hd">Fetch</div>

      <a onclick="getFetch()" href="javascript:;" class="weui_btn weui_btn_default">GET Fetch</a>
      <a onclick="getFetchSimple()" href="javascript:;" class="weui_btn weui_btn_default">GET Fetch (simple)</a>
      <a onclick="getFetchText()" href="javascript:;" class="weui_btn weui_btn_default">GET Fetch Text</a>
      <a onclick="getFetchJsonText()" href="javascript:;" class="weui_btn weui_btn_default">GET Fetch JSON Text</a>
      <a onclick="getFetch500()" href="javascript:;" class="weui_btn weui_btn_default">GET Fetch 500</a>
      <a onclick="putFetch()" href="javascript:;" class="weui_btn weui_btn_default">PUT Fetch</a>
      <a onclick="postFetch()" href="javascript:;" class="weui_btn weui_btn_default">POST Fetch</a>
      <a onclick="postFetchByRequest()" href="javascript:;" class="weui_btn weui_btn_default">POST Fetch Using XHR</a>
      <a onclick="optionsFetch()" href="javascript:;" class="weui_btn weui_btn_default">OPTIONS Fetch</a>
      <a onclick="fetchIOSLowBug()" href="javascript:;" class="weui_btn weui_btn_default">Fetch iOS LowBug</a>
      <a onclick="fetchStream()" href="javascript:;" class="weui_btn weui_btn_default">Fetch Steam</a>
    </div>

    <div class="section">
      <div class="hd">Others</div>

      <a onclick="sendBeacon()" href="javascript:;" class="weui_btn weui_btn_default">sendBeacon</a>
      <a onclick="axiosRequest('GET')" href="javascript:;" class="weui_btn weui_btn_default">Axios: GET</a>
      <a onclick="axiosRequest('POST')" href="javascript:;" class="weui_btn weui_btn_default">Axios: POST</a>
      <a onclick="zeptoRequest('POST')" href="javascript:;" class="weui_btn weui_btn_default">Zepto: POST</a>
      <a onclick="scrolling()" href="javascript:;" class="weui_btn weui_btn_default">Scrolling</a>
      <a onclick="crossDomain()" href="javascript:;" class="weui_btn weui_btn_default">Cross Domain</a>
      <a onclick="testWavesurfer()" href="javascript:;" class="weui_btn weui_btn_default">Wavesurfer.js</a>
    </div>

    <div class="section">
      <div class="hd">Exporter</div>

      <a onclick="callExportAdd()" href="javascript:;" class="weui_btn weui_btn_default">vConsole.network.add()</a>
      <a onclick="callExportUpdate()" href="javascript:;" class="weui_btn weui_btn_default">vConsole.network.update()</a>
      <a onclick="callExportClear()" href="javascript:;" class="weui_btn weui_btn_default">vConsole.network.clear()</a>
    </div>

    <div class="section">
      <div class="hd">Resources</div>

      <a onclick="postImage()" href="javascript:;" class="weui_btn weui_btn_default">POST Image</a>
      <a onclick="loadImgError()" href="javascript:;" class="weui_btn weui_btn_default">Load Img Error</a>
      <a onclick="loadScriptError()" href="javascript:;" class="weui_btn weui_btn_default">Load Script Error</a>
      <a onclick="loadVideoError()" href="javascript:;" class="weui_btn weui_btn_default">Load Video Error</a>
      <a onclick="loadLinkError()" href="javascript:;" class="weui_btn weui_btn_default">Load Link Error</a>
      <a onclick="loadAudioError()" href="javascript:;" class="weui_btn weui_btn_default">Load Audio Error</a>
    </div>
  </div>
</body>
</html>

<script>
const vConsole = new window.VConsole({
  // defaultPlugins: ['system'],
  // disableLogScrolling: true,
  onReady: function() {
    console.log('vConsole is ready.');
    vConsole.showPlugin('network');
  }
});

// setInterval(() => {
//   postAjax();
// }, 300);

function showPanel() {
  vConsole.showPlugin('network');
  vConsole.show();
}

function postAjax(postType, file = 'large.json') {
  showPanel();
  const xhr = new XMLHttpRequest();
  xhr.onload = () => {
    console.log('post XHR Response:', JSON.parse(xhr.response));
  };
  xhr.onerror = () => {
    console.log('post XHR Error');
  };
  xhr.onreadystatechange = () => {
    console.log('onreadystatechange', `readyState=${xhr.readyState}`, `status=${xhr.status}`);
  };

  let postData = {
    foo: 'bar',
    book: { id: 123, type: 'comic', uid: [4,5,6,7,8] },
    id: `${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}`,
    type: 'xhr',
    '<xss0>': '<xss1> XSS Attack!'
  };
  if (postType === 'json') {
    postData = JSON.stringify(postData);
  }
  console.log(xhr.setRequestHeader);
  xhr.open('POST', `./data/${file}?method=fetchPost&c=中文`);
  xhr.setRequestHeader.apply(xhr, ['custom-auth', 'foobar']);
  xhr.send(postData);
  // xhr.send(JSON.stringify({foo: 'bar', id: Math.random(), '<xss0>': '<xss1> XSS Attack!'}));
}

function getAjax() {
  const url = window.location.origin + '/dev/data/success.json?method=xhrGet&id=' + Math.random() + '&<xss0>';
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.setRequestHeader('custom-header', 'foobar');
  xhr.send();
  xhr.onload = () => {
    console.log('get XHR Response:', JSON.parse(xhr.response));
  };
  xhr.onerror = () => {
    console.log('get XHR Error');
  };
}

function putAjax() {
  showPanel();
  const url = window.location.origin + '/dev/data/success.json?method=xhrGet&id=' + Math.random() + '&<xss0>';

  let postData = {
    foo: 'bar',
    book: { id: 123, type: 'comic', uid: [4,5,6,7,8] },
    id: `${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}`,
    type: 'xhr',
    '<xss0>': '<xss1> XSS Attack!'
  };

  const xhr = new XMLHttpRequest();
  xhr.open('PUT', url);
  xhr.setRequestHeader('custom-header', 'foobar');
  xhr.send(postData);
  xhr.onload = () => {
    console.log('put XHR Response:', JSON.parse(xhr.response));
  };
  xhr.onerror = () => {
    console.log('put XHR Error');
  };
}

function getFetch() {
  showPanel();
  window.fetch('./data/success.json?method=fetchGet&id=' + Math.random(), {
    method: 'GET',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
  }).then((data) => {
    console.log('getFetch() response:', data);
    setTimeout(() => {
      data.json().then((res) => {
        console.log(res);
      });
    }, 3000);
    // return data;
    // return data.json();
  }).then((data) => {
    // console.log('getFetch() json:', data);
  });
}

function fetchIOSLowBug() {
  // need ios<11 to test
  window.fetch('./data/success.json?method=fetchGet&id=' + Math.random(), {
    method: 'GET',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
  }).then((data) => {
    return data.clone().json();
  }).then((data) => {
    console.log('fetchIOSLowBug Response:', data);
  }).catch((err) => {
    console.error('fetchIOSLowBug bug!!!:', err);
  });
}

function getFetchSimple() {
  window.fetch('./data/massive.json?type=fetchGet&id=' + Math.random()).then((data) => {
    return data.json();
  }).then((data) => {
    console.log('getFetchSimple Response:', data);
  });
}

function putFetch() {
  showPanel();
  window.fetch('./data/success.json?method=fetchPut&id=' + Math.random(), {
    method: 'PUT',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
    body: { foo: 'bar', id: Math.random(), type: 'fetch' },
  }).then((data) => {
    console.log('putFetch() response:', data);
    setTimeout(() => {
      data.json().then((res) => {
        console.log(res);
      });
    }, 3000);
    // return data;
    // return data.json();
  }).then((data) => {
    // console.log('putFetch() json:', data);
  });
}

function postFetch() {
  window.fetch('./data/success.json?method=fetchPost&<xss2>x=<xss2>', {
    method: 'POST',
    body: { foo: 'bar', id: Math.random(), type: 'fetch' },
    // body: new Blob([new ArrayBuffer(233)], { type: 'image/png' }),
    headers: {
      'custom-header': 'foobar',
      // 'content-type': 'application/json'
      // 'content-type': 'application/x-www-form-urlencoded'
      'content-type': 'multipart/form-data',
      'xss': '<xss1> XSS Attack!'
    },
  }).then((data) => {
    return data.json();
  }).then((data) => {
    console.log('post Fetch Response:', data);
  }).catch((error) => {
    console.error('post Fetch Error:', error);
  });
}

function postFetchByRequest() {
  const headers = new Headers();
  headers.append('custom-header', 'foobar');
  // headers.append('content-type', 'application/json');
  headers.append('content-type', 'application/x-www-form-urlencoded');
  const req = new Request('./data/success.json?method=fetchPost&id=' + Math.random(), {
    method: 'POST',
    body: { foo: 'bar', id: Math.random() },
    // body: new Blob([new ArrayBuffer(233)], { type: 'image/png' }),
    headers: headers,
  });
  window.fetch(req).then((data) => {
    return data.json();
  }).then((data) => {
    console.log('postFetchByRequest Response:', data);
  }).catch((error) => {
    console.error('postFetchByRequest Error:', error);
  });
}

function getFetchText() {
  window.fetch('./data/string.txt?type=fetchGet&id=' + Math.random(), {
    method: 'GET',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
  }).then((data) => {
    return data.text();
  }).then((data) => {
    console.log('getFetchText Response:', data);
  });
}

function getFetchJsonText() {
  window.fetch('./data/json.txt?type=fetchGet&id=' + Math.random(), {
    method: 'GET',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
  }).then((data) => {
    return data.text();
  }).then((data) => {
    console.log('getFetchJsonText Response:', data);
  });
}

function getFetch500() {
  window.fetch('./data/success.txt?type=fetchGet&s=500&id=' + Math.random(), {
    method: 'GET',
    headers: {
      'custom-header': 'foobar',
      'content-type': 'application/json'
    },
  }).then((data) => {
    console.log('Fetch Response:', data);
    return data.text();
  }).then((data) => {
    console.log('Fetch Data:', data);
  }).catch((e) => {
    console.error('Fetch Error:', e);
  });
}

function fetchStream() {
  vConsole.show();
  window.fetch('./data/stream.flv?id=' + Math.random()).then((response) => {
    console.log('then response', 'bodyUsed:', response.bodyUsed, 'locked:', response.body.locked);
    // console.log(response.text())
    // return;
    const reader = response.body.getReader();
    console.log('then response', 'bodyUsed:', response.bodyUsed, 'locked:', response.body.locked);
    let bytesReceived = 0;

    return reader.read().then(function process(result) {
        console.log('reader.read', 'bodyUsed:', response.bodyUsed, 'locked:', response.body.locked);
        if (result.done) {
          console.log('Failed to find match');
          return;
        }

        bytesReceived += result.value.length;
        console.log(`Received ${bytesReceived} bytes.`);

        if (bytesReceived > 3000000) {
          reader.cancel();
          console.log('Cancel.', response.status);
          return;
        }

        return reader.read().then(process);
      });
  });
}

function xhrStream(format = 'flv') {
  vConsole.show();
  const url = `./data/success.${format}?chunked=1&id=` + Math.random();
  const xhr = new XMLHttpRequest();
  xhr.timeout = 11000;
  console.log('xhr type:', typeof xhr, xhr instanceof XMLHttpRequest);
  xhr.open('GET', url);
  xhr.send();
  xhr.onreadystatechange = () => {
    console.log('XHR onreadystatechange:', 'readyState:', xhr.readyState, 'responseType:', xhr.responseType);
  };
  xhr.onprogress = (e) => {
    // console.log('XHR onprogress:', 'readyState:', xhr.readyState, 'status:', xhr.status, 'loaded:', e.loaded, 'timeStamp:', e.timeStamp);
    if (e.loaded > 3000000) {
      xhr.abort();
    }
  };
  xhr.onloadstart = (e) => {
    // console.log('XHR onloadstart:', e);
  };
  xhr.onloadend = (e) => {
    // console.log('XHR onloadend:', 'readyState:', xhr.readyState, xhr.status, e);
  };
  xhr.onload = (e) => {
    console.log('XHR onload:', 'readyState:', xhr.readyState, xhr.status, xhr.responseType);
  };
  xhr.onerror = (e) => {
    console.log('XHR onerror:', e);
  };
  xhr.onabort = (e) => {
    console.log('XHR onabort:', xhr.readyState, xhr.status, e);
  };
  xhr.ontimeout = (e) => {
    console.log('XHR ontimeout:', e);
  }
}

function postImage() {
  console.info('postImage() Start, response should be logged after End');
  const xhr = new XMLHttpRequest();
  xhr.open('POST', './lib/snapshot/panel_log.jpg?method=xhrPost&id=' + Math.random());
  xhr.send();

  window.fetch('./lib/snapshot/qrcode.png?method=fetchPost&id=' + Math.random(), {
    method: 'POST',
  });
  console.info('postImage() End');
}

function sendBeacon() {
  vConsole.show();
  console.info('sendBeacon() Start, response should be logged after End');
  window.navigator.sendBeacon('./data/success.json?method=beacon', JSON.stringify({
    foo: 'bar',
    id: Math.random(),
    type: 'sendBeacon'
  }));
  console.info('sendBeacon() End');
}

function axiosRequest(method) {
  vConsole.show();
  axios({
    method,
    url: './data/success.json?method=axios&r=' + Math.random(),
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
      'foo': 'bar',
    },
    data: {
      foo: 'bar'
    }
  })
  .then(function(response) {
    console.log('axiosRequest response:', response);
  })
  .catch(function(error) {
    console.log('axiosRequest error:', error);
  });
}

function zeptoRequest(method = 'GET') {
  vConsole.show();
  $.ajax({
    type: method,
    async: true,
    url: './data/success.json?method=zepto&r=' + Math.random(),
    headers: {
      'content-type': 'application/x-www-form-urlencoded',
      'custom-auth': 'foobar',
      'foo': 'bar',
    },
    data: {
      foo: 'bar',
    },
    xhrFields:{
      withCredentials: true
    },
    dataType: 'json',
    success(data) {
      console.log('zeptoRequest response:', data);
    },
  });
}

function optionsXHR() {
  console.info('optionsXHR() Start');
  const url = window.location.origin + '/dev/success.json?method=optionsXHR&s=200&id=' + Math.random() + '&<xss0>';
  const xhr = new XMLHttpRequest();

  let postData = {
    foo: 'bar',
    book: { id: 123, type: 'comic', uid: [4,5,6,7,8] },
    id: `${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}${Math.random()}`,
    type: 'xhr',
    '<xss0>': '<xss1> XSS Attack!'
  };

  xhr.open('OPTIONS', url);
  xhr.setRequestHeader('custom-header', 'foobar');
  xhr.send(postData);
  xhr.onload = () => {
    console.log('optionsXHR Response:', xhr.response);
  };
  xhr.onerror = () => {
    console.log('optionsXHR Error');
  };
  console.info('optionsXHR() End');
}

function optionsFetch() {
  console.info('optionsFetch() Start');
  window.fetch('./data/success.json?method=optionsFetch&s=203&t=300', {
    method: 'OPTIONS',
    body: { foo: 'bar', id: Math.random(), type: 'fetch', 'method': 'put', },
  }).then((data) => {
    console.log('optionsFetch Response:', data);
  }).catch((error) => {
    console.error('optionsFetch Error:', error);
  });
  console.info('optionsFetch() End');
}

function testWavesurfer() {
  showPanel();
  const div = document.createElement('DIV');
  div.id = 'waveform';
  document.body.append(div);
  var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    waveColor: 'violet',
    progressColor: 'purple'
  });
  wavesurfer.load('./data/a.wav?method=fetch');
}

function scrolling() {
  vConsole.setOption('maxNetworkNumber', 60);
  let n = 0
  let t = setInterval(() => {
    n++;
    if (n > 500) {
      clearInterval(t);
      vConsole.setOption('maxNetworkNumber', 25);
    }
    getAjax();
  }, 150);
}

let item = null;
function callExportAdd() {
  item = vConsole.network.add({
    url: 'https://foo.bar.com/hello/world.json?aaa=bbb',
    status: 100,
    method: 'PUT',
    requestHeader: {
      'foobar': 'yes',
    },
    getData: {
      'ccc': 'ddd',
    },
    postData: {
      'eee': 'fff',
    },
  });
  showPanel()
}

function callExportUpdate() {
  if (!item) {
    callExportAdd();
  }
  item.status = 110;
  item.endTime = Date.now();
  item.responseType = 'json';
  item.response = {
    foo: 'bar',
    rand: Math.random(),
  };
  item.header = {
    'barfoo': 'no',
  };
  item.getData.zzz = 'yyy';
  vConsole.network.update(item.id, item);
  setTimeout(() => {
    item.status = 200;
    item.response = {
      foo2: 'bar2',
    };
    vConsole.network.update(item.id, item);
  }, 2000);
  showPanel()
}

function callExportClear() {
  vConsole.network.clear();
}

function crossDomain() {
  const res = window.fetch('http://baidu.com/?foo=bar', {
    method: 'GET',
  }).then((data) => {
    console.log('crossDomain() Response:', data);
  }).catch((error) => {
    console.error('crossDomain() Error:', error);
  });
}

function loadImgError() {
  console.info('loadImgError() Start');
  const img = new Image();
  img.src = 'http://xxxx.jpg';
  document.body.appendChild(img);
  img.onerror = () => {
    console.info('loadImgError() End');
  }
}

function loadScriptError() {
  console.info('loadScriptError() Start');
  const scri = document.createElement("script");
  scri.src = 'http://xxxx.js';
  document.body.appendChild(scri);
  scri.onerror = () => {
    console.info('loadScriptError() End');
  }
}

function loadVideoError() {
  console.info('loadVideoError() Start');
  const vid = document.createElement("video");
  vid.src = 'http://xxxx.mp4';
  document.body.appendChild(vid);
  vid.onerror = () => {
    console.info('loadVideoError() End');
  }
}

function loadLinkError() {
  console.info('loadLinkError() Start');
  const link = document.createElement("link");
  link.rel = 'stylesheet';
  link.type = 'text/css';
  link.href = './data/a.css?s=404';
  document.body.appendChild(link);
  link.onerror = () => {
    console.info('loadLinkError() End');
  }
}

function loadAudioError() {
  console.info('loadAudioError() Start');
  const audio = document.createElement("Audio");
  audio.src = 'http://xxxx.mp3';
  document.body.appendChild(audio);
  audio.onerror = () => {
    console.info('loadAudioError() End');
  }
}

</script>